GIT教程

您所在的位置:网站首页 git 底层命令 GIT教程

GIT教程

2023-08-26 04:33| 来源: 网络整理| 查看: 265

GIT教程

图片

Git基础

​ Git官网(下载速度慢) https://git-scm.com/

​ 阿里云加速(下载速度快):https://npm.taobao.org/mirrors/git-for-windows/

01——版本控制 集中式(svn) svn因为每次存的都是差异 需要的硬盘空间会相对的小一点 可是回滚的速度会很慢 优点: 代码存放在单一的服务器上 便于项目的管理 缺点: 服务器宕机: 员工写的代码得不到保障 服务器炸了: 整个项目的历史记录都会丢失 分布式(git) git每次存的都是项目的完整快照 需要的硬盘空间会相对大一点 (Git团队对代码做了极致的压缩 最终需要的实际空间比svn多不了太多 可是Git的回滚速度极快) 优点: 完全的分布式 缺点: 学习起来比SVN陡峭 02——版本管理

图片

版本库👉.git

当我们使用git管理文件时,比如git init时,会创建出一个.git文件,我们把这个文件称为版本库。.git文件另外一个作用就是它在创建的时候,会自动创建master分支,并且将HEAD指针指向master分支。

工作区

本地项目存放文件的位置,即workspace

暂存区(Index/Stage)

暂时存放文件的地方,通过add命令将工作区的文件加到缓冲区

本地仓库(Repository)

通常情况下,我们使用commit命令可以将暂存区的文件添加到本地仓库通常而言,HEAD指针指向的是master分支

远程仓库(Remote)

GitHub托管项目时,它就是一个远程仓库通常我们使用clone命令将远程仓库代码拷贝下来,本地代码更新后,通过push推送到远程仓库

工作流程:「工作区 -> 暂存区 -> 版本库」

「Git是什么」

​ Git是一个版本管理控制系统(缩写VCS),它可以在任何时间点,将文档的状态作为更新记录保存起来,也可以在任何时间点,将更新记录恢复回来。

图片

「基本工作流程」

图片

git仓库暂存区工作目录用于存放提交记录临时存放被修改文件被Git管理的项目目录 「Git底层命令」git对象、树对象、提交对象

​ git存储数据,一个文件对应一条内容,校验和(生成的哈希值)的前两个字符用于命名子目录,余下的38个字符则用作文件名

git对象: Git 的核心部分是一个简单的键值对数据库 。 你可以向该数据库插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次检索该内容 git hash-object -w fileUrl : 生成一个key(hash值):val(压缩后的文件内容)键值对存到 .git/objects

​ 在Git中,文件名并没有被保存——我们仅保存了文件的内容 解决方案:树对象 tree对象:fileUrl–文件路径 所有内容均以树对象和数据对象 (git 对象 的形式存储,其中树对象对应了 UNIX 中的目录项,数据对象 (git 对象 则大致上对应文件内容

git update-index --add --cacheinfo 100644 hash test.txt : 往暂存区添加一条记录(让git对象 对应上 文件名 )存到.git/index git write-tree : 生成树对象存到.git/objects

image-20210527101845249

​ 现在有三个树对象 (执行了三次 write tree ),分别代表了我们想要跟踪的不同项目快照。然而问题依旧:若想重用这些快照,你 必须记住所有三个SHA 1 哈希值。 并且,你也完全不知道是谁保存了这些快照,在什么时刻保存的,以及为什么保存这些快照。 而以上这些,正是提交对象( commit object)能为你保存的基本信息

​ 我们 可以通过调用 commit tree 命令创建一个提交对象,为此需要指定一个树对象的 SHA 1 值,以及该提交的父提交对象(如果有的话 第一次将暂存区做快照就没有父对象)

commit对象 echo 'first commit' | git commit-tree treehash : 生成一个提交对象存到.git/objects 对以上对象的查询 git commit tree 不但生成提交对象 而且会将对应的快照(树对象)提交到本地库中 echo 'second commit' | git commit-tree 0155eb -p hash值(第一次提交对象hash) // cac0cab538b970a37ea1e769cbbde608743bc96d echo 'third commit' | git commit-tree 3c4e9c -p cac0cab // 1a410efbd13591db07496601ebc7a059dd55cfe9 git cat-file -p hash : 拿对应对象的内容 git cat-file -t hash : 拿对应对象的类型

image-20210527104959682

查看暂存区 git ls-files -s 「Git高层命令」CRUD C(新增) Create 命令: git init 解析: 要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行: git init 作用: 初始化后,在当前目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中。不过目前,仅仅是按照既有的结构框架 初始化好了里边所有的文件和目录,但我们还没有开始跟踪管理项目中的任何一个文件。 U(修改) Update 在工作目录中修改文件 git status // 确定文件当前处于什么状态 git add ./ // 跟踪一个新文件,放到暂存区,同时做成git对象放到版本库(工作目录到版本库,再到暂存区) git commit -m "msg" D(删除 & 重命名) Delete git rm 要删除的文件 git mv 老文件 新文件 git status git status git commit -m "msg" git commit -m "msg" R(查询) Retrieve git status : 查看工作目录中文件的状态(已跟踪(已提交 已暂存 已修改) 未跟踪) git diff : 查看未暂存的修改 git diff --cache : 查看未提交的暂存 git log --oneline : 查看提交记录 分支 分支的本质其实就是一个提交对象!!! HEAD: 是一个指针 它默认指向master分支 切换分支时其实就是让HEAD指向不同的分支 每次有新的提交时 HEAD都会带着当前指向的分支 一起往前移动 git log --oneline --decorate --graph --all : 查看整个项目的分支图 git branch : 查看分支列表 git branch -v: 查看分支指向的最新的提交 git branch name : 在当前提交对象上创建新的分支 git branch name commithash: 在指定的提交对象上创建新的分支 git checkout name : 切换分支 git branch -d name : 删除空的分支 删除已经被合并的分支 git branch -D name : 强制删除分支 「Git使用前配置」

在使用git前,需要告诉git你是谁,在向git仓库中提交时需要用到。

配置提交人姓名:git config --global user.name 提交人姓名 // 全局配置 不加global就只针对项目配置提交人邮箱:git config --global user.email 提交人邮箱查看git配置信息:git config --list取消配置信息 git config --global --unset user.name取消配置信息 git config --global --unset user.email 「注意」 如果要对配置信息进行修改,重复上述命令即可。配置只需要执行一次。 「配置别名」

​ Git并不会在你输入部分命令时自动推断出你想要的命令。 如果不想每次都输入完整的 Git 命令,可以通过 git config 文件来轻松地为每一个命令设置一个别名。

$ git config --global alias.co checkout $ git config --global a lias.br branch $ git config --global alias.ci commit $ git config --global alias.st status // 当要输入git commit 时,只需要输入 git ci 「Git提交步骤」 git init初始化git仓库 hooks 目录包含客户端或服务端的钩子脚本; info 包含一个全局性排除文件 logs 保存日志信息 objects 目录存储所有数据内容; refs 目录存储指向数据的提交对象的指针(分支) config 文件包含项目特有的配置选项 description 用来显示对仓库的描述信息 HEAD 文件指示目前被检出的分支 index 文件保存暂存区信息 git status查看文件状态 git add 文件列表 追踪文件 git commit -m 提交信息向本地仓库中提交代码 git log查看提交记录

git rm 文件名 删除工作目录中对应的文件,再将修改添加到暂存区

git mv 原文件名 新文件名 将工作目录中的文件进行重命名,再将修改添加到暂存区

git push https://github.com/ovfan/git-demo.git master本地仓库推送到GitHub远程仓库 git remote add origin https://github.com/ovfan/git-demo.git 为远端仓库地址添加别名。 添加完别名后,下次推送使用git push origin master git push -u 远程仓库地址别名 分支名称 -u 记住推送地址及分支,下次推送只需要输入git push即可 「撤销」 用暂存区中的文件覆盖工作目录中的文件:git checkout 文件将文件从暂存区中删除:git rm --cached 文件将git仓库中指定的更新记录恢复出来,并且覆盖暂存区和工作区目录:git reset --hard commitID

​ 当暂存区域已经准备妥当可以提交时,在此之前,请一定要确认还有什么修改过的或新建的文件还没有 git add 过,否则提交的时候不会记录这些还没暂存起来的变化。所以,每次准备提交前,先用 git status 看下,是不是都已暂存起来了,然后再运行提交命令 git commit

​ 工作目录下面的所有文件都不外乎这两种状态: 已跟踪(已提交 已修改 或者 已暂存)或 未跟踪

克隆仓库 后的文件

​ 如果在克隆仓库之后立即执行此命令,会看到类似这样的输出:

On branch master nothing to commit, working directory clean 未跟踪文件

​ 如果 创建一个新文件 README 保存退出后运行 git status 会看到该文件出现 ​ 在未跟踪文件列表中:

On branch master ​ U ntracked files: ​ (use "git add ..." to include in what will be ​ README ​ nothing added to commit but untracked files present (use "git add" to track) 跟踪新文件(暂存)

​ 命令: git add 文件名 ​ 作用: 跟踪一个新文件 ​ 再次运行 git status 命令,会看到 README 文件已被跟踪,并处于暂存状态:

Changes to be committed: ​ (use "git reset HEAD ..." to ​ new file: README 暂存已修改文件

​ Git 只不过暂存了你运行 git add 命令时的版本,如果现在提交,那么提交的是添加注释前的版本,而非当前工作目录中的版本。所以,运行gitadd 之后又作了修订的文件,需要重新运行 git add 把最新版本重新暂存起来:

$ git add README $ git status On branch master Changes to be committed: (use "git reset HEAD ..." to new file: README 查看已暂存和未暂存的更新

​ 如果要查看具体修改了什么地方,可以用 git diff 命令 这个命令 它已经能 解决 我们两个问题了: 当前做的哪些更新还没有暂存?有哪些更新已经暂存起来准备好了下次提交?

1. 当前做的哪些更新还没有暂存? 命令: git diff 不加参数直接输入 git diff 2. 有哪些更新已经暂存起来准备好了下次提交? 命令: git diff cached 或者 git diff staged(1.6.1 以上

Git进阶

01----分支

​ 为了便于理解,可以认为分支就是当前工作目录中代码的一份副本,使用分支,可以让我们从开发主线上分离出来,以免影响开发主线。分支本质是一个提交对象,所有的分支都会有机会被HEAD所引用(HEAD一个时刻只会指向一个分支),当我们有新的提交的时候 HEAD会携带当前持有的分支往前移动

Git 的分支,其实本质上仅仅是指向提交对象的可变指针 。 Git 的默认分支名字是 master 。 在多次提交操作之后,你其实已经有一个指 向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。

「分支细分」 主分支(master):第一次向 git 仓库中提交更新记录时自动产生的一个分支。

图片

​ 主分支,用于部署生产环境的分支,确保稳定性。

​ master分支一般由develop以及hotfix分支合并,任何情况下都不能直接修改代码。

开发分支(develop):作为开发的分支,基于 master 分支创建。

develop为开发分支,通常情况下,保存最新完成以及bug修复后的代码。

开发新功能时,feature分支都是基于develop分支下创建的。

图片

功能分支(feature):作为开发具体功能的分支,基于开发分支创建。

开发新功能,基本上以develop为基础创建feature分支。

分支命名:feature/ 开头的为特性分支, 命名规则: feature/user_module、 feature/cart_module。

图片

**release分支:**release 为预上线分支,发布提测阶段,会release分支代码为基准提测。

hotfix分支:分支命名:hotfix/ 开头的为修复分支,它的命名规则与 feature 分支类似。线上出现紧急问题时,需要及时修复,以master分支为基线,创建hotfix分支,修复完成后,需要合并到master分支和develop分支。

「功能分支 -> 开发分支 -> 主分支」

​ 只在 master 主分支上保留完全稳定的代码——有可能仅仅是已经发布或即将发布的代码。 他们还有一些名为 develop 或者 feature 的平行分支,被用来做后续开发或者测试稳定性——这些分支不必保持绝对稳定,但是一旦达到稳定状态,它们就可以被合并入 master 分支了。等待下一次的发布。

「分支命令」

git branch 查看本地分支

git branch -r查看远程分支

git branch 分支名称创建分支

git checkout -b 分支名称创建并切换到新建分支

git checkout 分支名称切换分支

git merge 来源分支合并分支

git branch -d 分支名称删除分支

分支被合并后才允许删除git branch -D强制删除

git branch -m 重命名分支

git log --oneline --decorate --graph --all 查看项目分叉历史

git branch name(旧版本名字) commitHash(旧版本的hash值) 新建一个分支并且使分支指向对应的提交对象

git add .全部上传到缓存区

git add 指定文件指定文件上传到缓存区 查看分支列表 : git branch 查看合并到当前分支的分支列表: git branch --merged 一旦出现在这个列表中 就应该删除 查看没有合并到当前分支的分支列表: git branch --no-merged 一旦出现在这个列表中 就应该观察一下是否需要合并 「暂时保存更改」—Git存储

​ 在git 中,可以暂时提取分支上所有的改动并存储,让开发人员得到一个干净的工作副本,临时转向其他工作。

​ 注:在切换分支时,如果当前分支上有未暂存的修改 或者 有未提交的暂存,分支可以切换成功,但是可能会污染其他分支

使用场景:分支临时切换

存储临时改动:git stash恢复改动:git stash pop 「Git分支的注意点」 在切换的时候 一定要保证当前分支是干净的!!! 允许切换分支: 分支上所有的内容处于 已提交状态 (避免)分支上的内容是初始化创建 处于未跟踪状态 (避免)分支上的内容是初始化创建 第一次处于已暂存状态 不允许切分支: 分支上所有的内容处于 已修改状态 或 第二次以后的已暂存状态 在分支上的工作做到一半时 如果有切换分支的需求, 我们应该将现有的工作存储起来 git stash : 会将当前分支上的工作推到一个栈中 分支切换 ---> 进行其他工作 ---> 完成其他工作后 ---> 切回原分支 git stash apply : 将栈顶的工作内容还原 但不让任何内容出栈 git stash drop : 取出栈顶的工作内容后 就应该将其删除(出栈) ** git stash pop : git stash apply + git stash drop 加上将要移除的储藏的名字来移除它 git stash list : 查看存储 「实际案例分析」 工作流:

​ 1 开发某个网站。 ​ 2 为实现某个新的需求,创建一个分支。 ​ 3 在这个分支上开展工作。 ​ 正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补。你将按照如下方式来处理: ​ 1 切换到你的线上分支( production branch )。 ​ 2 为这个紧急任务新建一个分支,并在其中修复它。 ​ 3 在测试通过之后,切换回线上分支,然后合并这 个修补分支,最后将改动推送到线上分支。 ​ 4 切换回你最初工作的分支上,继续工作。

Git 流:

​ 首先,我们假设你正在你的项目上工作,并且已经有一些提交。

image-20210528100741565

​ 现在,你已经决定要解决你的公司使用的问题追踪系统中的#53 问题。 想要新建一个分支并同时切换到那个分支上,你可以运行一个带有 b 参数的 git checkout命令

git checkout b iss53 相当于 git branch iss53 git checkout iss53

image-20210528100816390

你继续在#53 问题上工作,并且做了一些提交。 在此过程中, iss53 分支在不断的向前推进,因为你已经检出到该分支。

image-20210528100857598

​ !!!现在你接到那个电话,有个紧急问题等待你来解决

​ 有了 Git 的帮助,你不必把这个紧急问题和 iss53 的修改混在一起,你也不需要花大力气来还原关于 53# 问题的修改,然后再添加关于这个紧急问题的修改,最后将这个修改提交到线上分支。 你所要做的仅仅是切换回 master 分支。但是,在你这么做之前,要留意你的工作目录和暂存 区里那些还没有被提交的修改,它可能会和你即将检出的分支产生冲突从而阻止 Git 切换到该分支 。 最好的方法是,在你切换分支之前,保持好一个干净的状态。 (提交你的所有修改)

git checkout master // 切换回主的master

​ 这个时候,你的工作目录和你在开始 #53 问题之前一模一样,现在你可以专心修复紧急问题了。 请牢记:当你切换分支的时候, Git 会重置你的工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。 Git 会 自动添加、删除、修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样。

​ 接下来,你要修复这个紧急问题。 让我们建立一个针对该紧急问题的分支( hotfix branch ),在该分支上工作直到问题解决。

git checkout -b hotfix 做出修改 git commit -a -m 'fixed the broken email address'

image-20210528101105136

​ 你可以运行你 的测试,确保你的修改是正确的,然后将其合并回你的 master 分支来部署到线上。 你可以使用 git merge 命令来达到上述目的

git checkout master git merge hotfix

​ 在合并的时候, 有时候会出现 快进( fast forward 这个词。 由于当前 master 分支所指向的提交是你当前提交的直接上游,所以 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针 向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧 这就叫做 快进( fast forward)

image-20210528101150982

​ 关于这个紧急问题的解决方案发布之后,你准备回到被打断之前时的工作中。 然而,你应该先删除 hotfix 分支,因为你已经不再需要它了master 分支已经指向了同一个位置。 你可以使 用带 d 选项的 git branch 命令来删除分支 。 现在你可以切换回你正在工作的分支继续你的工作,也就是针对 #53 问题的那个分支

git branch -d hotfix git checkout iss53

image-20210528101233214

​ 你在 hotfix 分支上所做的工作并没有包含到 iss53 分支中。 如果你需要拉取 hotfix 所做的修改,你可以使用 git merge master 命令将 master 分支合并入 iss53 分支,或者你也可以等到 iss53 分支完成其使命,再将其合并回 master 分支。

git checkout master git merge iss53

image-20210528101338942

最终删除 iss 53 号分支 git branch -d iss53 冲突

​ 有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改, Git 就没法干净的合并它们。 如果你对 #53 问题的修改和有关 hotfix 的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来 查看那些因包含合并冲突而处于未合并( unmerged)状态的文件。在你解决了所有文件 里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件, Git 就会将它们标记为冲突已解决

「后悔药」 撤销工作目录的修改 : git checkout -- filename // 作用:将在工作目录中对文件的修改撤销 撤销暂存区的修改 : git reset HEAD filename // 作用:将文件从暂存区中撤回到工作目录 撤销提交 : git commit --amend // 作用:注释写错了可以修改一次 这个命令会将暂存区中的文件提交。如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息(注释内容) 如果 你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作 git commit -m 'initial commit' git add forgotten_file git commit -amend 最终你只会有一个提交 第二次提交将代替第一次提交的结果 「reset三部曲」 // 移动 HEAD git reset --soft commithash ---> 用commithash的内容重置HEAD内容 git reset [--mixed] commithash ---> 用commithash的内容重置HEAD内容 重置暂存区 git reset --hard commithash ---> 用commithash的内容重置HEAD内容 重置暂存区 重置工作目录 「路径reset」

所有的路径reset都要省略第一步!!!

第一步是重置HEAD内容 我们知道HEAD本质指向一个分支 分支的本质是一个提交对象 提交对象 指向一个树对象 树对象又很有可能指向多个git对象 一个git对象代表一个文件!!! HEAD可以代表一系列文件的状态!!!! git reset [--mixed] commithash filename 用commithash中filename的内容重置暂存区 「checkout深入理解」 git checkout brancname 跟 git reset --hard commithash特别像 共同点 都需要重置 HEAD 暂存区 工作目录 区别 checkout对工作目录是安全的 reset --hard是强制覆盖 checkout动HEAD时不会带着分支走而是切换分支 reset --hard时是带着分支走 checkout + 路径 git checkout commithash filename 重置暂存区 重置工作目录 git checkout -- filename 重置工作目录 「Git基本流程细化」 【初始化仓库】git init

​ 当我们运行 git init ,这会创建一个 Git 仓库,其中的 HEAD 引用指向未创建的分支。此时,只有工作目录有内容

image-20210529135610568

【获取工作目录内容】git add

​ 现在我们想要提交这个文件,所以用 git add 来获取工作目录中的内容,并将其复制到索引中

image-20210529135630497

【保存快照并创建提交对象】git commit

​ 接着运行 git commit ,它会取得索引中的内容并将它保存为一个永久的快照,然后创建一个指向该快照的提交对象,最后更新 master 来指向本次提交。

commit -m 和 commit -am 的区别

​ git commit -m “” 只会提交添加到缓存区的文件(只提交添加的)

​ git commit -a -m “” 能提交修改过,但是没有添加到缓存区的文件(修改过的就能提交)

image-20210529135820650

【状态查询】git status

​ 此时如果我们运行 git status ,会发现没有任何改动,因为现在三棵树完全相同

【文件修改并提交】

​ 现在我们想要对文件进行修改然后提交它。 我们将会经历同样的过程;首先在工作目录中修改文件。 我们称其为该文件的 v2 版本,并将它标记为红色

image-20210529135936655

​ 如果现在运行 git status ,我们会看到文件显示在 “Changes not staged for commit,” 下面并被标记为红色,因为该条目在索引与工作目录之间存在不同。接着我们运行 git add 来将它暂存到索引中。

image-20210529140020003

​ 此时,由于索引和 HEAD 不同,若运行 git status 的话就 会看到“Changes to be committed” 下的该文件变为绿色 也就是说,现在预期的下一次提交与上一次提交不同。 最后,我们运行 git commit 来完成提交。

image-20210529140109055

​ 现在运行 git status 会没有输出,因为三棵树又变得相同了

【切换分支或克隆】

​ 切换分支或克隆的过程也类似。 当检出一个分支时,它会修改 HEAD 指向 新的分支引用,将 索引 填充为该次提交的快照,然后将 索引 的内容复制到工作目录中 。

【重置reset三部曲】 移动 HEAD:

​ reset 做的第一件事是移动 HEAD 的指向。假设我们再次修改了 file.txt 文件并第三次提交它。 现在的历史看起来是这样

image-20210529140445764

​ git reset -soft HEAD~ :这与改变 HEAD 自身不同( checkout 所做的); reset 移动 HEAD 指向的分支。 HEAD~ 加个波浪号 代表回到上一次的 HEAD指向

image-20210529140543239

​ 看一眼上图,理解一下发生的事情:它本质上是撤销了上一次 git commit 命令。 当你在运行 git commit 时, Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交 。

​ 当你将它 reset 回 HEAD~ (HEAD 的父结点)时,其实就是把该分支移动回原来的位置,而不会改变索引和工作目录。 现在你可以更新索引并再次运行 git commit 来完成 git commit --amend 所要做的事情了。

​ 注:如果还想回到v3版本,可以git reflog 找到v3版本的hash值,然后git reset --soft [hash值]

更新暂存区(索引)

image-20210529140915504

​ !!!注意 git reset HEAD~ 等同于 git reset --mixed HEAD~

​ 理解一下发生的事情:它依然会撤销一上次 提交 ,但还会 取消暂存 所有的东西。 于是,我们回滚到了所有 git add 和 git commit 的命令执行之前。

更新工作目录

image-20210529141027192

​ 你撤销了最后的提交、 git add 和 git commit 命令 以及 工作目录中的所有工作。

checkout [branch] 与reset --hard [branch]的区别

​ 不带路径:

​ 首先不同于 reset --hard,checkout 对工作目录是安全的,它会通过检查来确保不会将已更改的文件弄丢。而 reset --hard 则会不做检查就全面地替换所有东西。

​ 第二个重要的区别是如何更新 HEAD。 reset 会移动 HEAD 分支的指向,而 checkout 只会移动 HEAD 自身来指向另一个分支。

image-20210529142152968

​ 带路径:

git checkout commithash

​ 运行 checkout 的另一种方式就是指定一个文件路径,这会像 reset 一样不会移动 HEAD 。 它就像是 git reset --hard [branch] file。 这样对工作目录并不安全,它也不会移动 HEAD 将会跳过第 1 步 更新暂存区 和 工 作目录

git checkout -- // 相比于 git reset --hard commitHash 跟文件名的形式第一 第二步都没做 【数据恢复】git reflog

​ 当你正在 工作时, Git 会默默地记录每一次你改变 HEAD 时它的值。 每一次你提交或改变分支,引用日志都会被更新

​ git reflog 并不能显示 足够多的信息。 为了使显示的信息更加有用,我们可以执行 git log -g ,这个命令会以标准日志的格式输出引用日志

​ 例如下面的那个就是你丢失的提交,你可以通过创建一个新的分支指向这个提交来恢复它。 例如,你可以创建一个名为 recover branch 的分支指向这个提交( ab1afef)

git branch recover branch ab1afef

​ 现在有一个名为 recover branch 的分支是你的 master 分支曾经指向的地方,再一次使得前两次提交可到达。

【打标签tag】

Git 可以给历史中的某一个提交打上标签,以示重要。

列出标签 git tag git tag -l 'v1.8.5*' v1.8.5 v1.8.5-rc0 v1.8.5 rc1 v1.8.5 rc2 v1.8.5 rc3 v1.8.5.1 v1.8.5.2 v1.8.5.3 创建标签

​ Git使用两种主要类型的标签:轻量标签 与 附注标签

​ 轻量标签很像一个不会改变的分支—它只是一个特定提交的引用

git tag v1.4 git tag v1.4 commitHash // 附注标签是存储在 G it 数据库中的一个完整对象。 它们是可以被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;等等 git tag -a v1.4 git tag -a v1.4 commitHash git tag -a v1.4 commitHash m 'my version 1.4' 查看特定标签: git show tagname //git show可以显示任意类型的对象( git 对 象 树对象 提交对象 tag 对象) 远程标签 默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到 共享服务器上。你可以运行 git push origin [tagname] 如果想要一次性推送很多标签,也可以使用带有--tags 选项的 git push 命令。这将会把所有不在远程仓库 服务器上的标签全部传送到那里。 git push origin --tags 删除标签 删除标签要删除掉你本地仓库上的 标签,可以使用命令 git tag -d < tagname>。 应该注意的是上述命令并不会从任何远程仓库中移除这个标签,你必须使用 git push :refs/tags/ 来更新你的远程仓库: git push origin :refs/tags/v1.4 检出标签 如果你想查看某个标签所指向的文件版本,可以使用git checkout 命令 git checkout tagname 02-----GitHub

当和开发团队共享数据时,设置一个远程仓库,可以把它看成一个文件管理服务器,利用这个服务器可以与开发团队的其他成员进行数据交换。

「三个必须懂得概念」 本地分支 创建本地分支,在需要打包的文件根目录下 git init --> git add * --> git commit -m “message" 远程跟踪分支(remote/分支名) 在GitHub上新建仓库,复制关联代码 git remote add origin xxx 到本地运行 远程分支 git push oringin master (先关联再推送) 「远程协作的基本流程」 第一步: 项目经理创建一个空的远程仓库 第二步: 项目经理创建一个待推送的本地仓库 第三步: 为远程仓库配别名 配完用户名 邮箱 git remote add //添加一个新的远程 Git仓库,同时指定一个你可以轻松引用的简写 git remote -v // 显示远程仓库使用的 Git 别名 与其对应的 URL git remote show [remote-name] // 查看某一个远程仓库的更多信息 git remote rename pb paul // 重命名 git remote rm [remote-name]//如果因为一些原因想要移除一个远程仓库 你已经从服务器上搬走了或不再想 使用某一个特定的镜像了,又或者某一个贡献者不再贡献了 第四步: 在本地仓库中初始化代码 提交代码 第五步: 推送 git push [remote-name] [branch-name] // 将本地项目的master分支推送到 origin(别名) 服务器 第六步: 邀请成员 // 如果你想与他人合作,并想给他们提交的权限,你需要把他们添加为 Collaborators,别人接受 第七步: 成员克隆远程仓库 git clone url (克隆时不需要 git init 初始化) // 默认克隆时为远程仓库起的别名为 origin 第八步: 成员做出修改 第九步: 成员推送自己的修改 git push [remote-name] [branch-name] 第十步: 项目经理拉取成员的修改 git fetch [remote-name] //必须注意 git fetch 命令会将数据拉取到你的本地仓库 它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。 git merge [远程跟踪分支] 「远程跟踪分支」 远程跟踪分支

​ 利用远程跟踪分支将本地分支与远程分支进行交互,远程跟踪分支 是远程分支状态的引用。它们是你不能移动的本地分支。当你做任何网络通信操作时,它们会自动移动。

当克隆 一个仓库时,它通常会自动地创建一个跟踪 origin/master 的 master 分支 本地没有分支 git checkout --track 远程跟踪分支(remote/分支名) 本地已经创建了分支 git branch -u 远程跟踪分支(remote/分支名)

​ 假设你的网络里有一个在 git.ourcompany.com 的 Git 服务器。 如果你从这里克隆, Git 的 clone 命令会为你自动将其命名为 origin ,拉取它的所有数据,创建一个指向它的 master 分支的指针,并且在本地将其命名为 origin/master 。 Git 也会给你一个与 origin master 分支在指向同一个地方的本地 master 分支,这样你就有工作的基础

image-20210529164413750

​ 如果你在本地的 master 分支做了一些工作,然而在同一时间,其他人推送提交到 git.ourcompany.com 并更新了它的 master 分支,那么 你们 的提交历史将向不同的方向前进。 只要你不与 origin 服务器连接,你的origin /master 指针就不会移动

image-20210529164459894

​ 如果要同步你的工作,运行 git fetch origin 命令。 这个命令查找 “origin” 是哪一个服务器(在本例中,它是 git.ourcompany.com从中抓取本地没有的数据,并且更新本地数据库,移动 origin/master 指针指向新的、更新后的位置。

推送其他分支

​ 当你想要公开分享一个分支时,需要将其推送到有写入权限的远程仓库上。 本地的分支并不会自动与远程仓库同步。 你必须显式地推送想要分享的分支。 这样,你就可以把不愿意分享的内容放到私人分支上,而将需要和别人协作的内容推送到公开分支

​ 如果希望和别人一起在名为 serverfix 的分支上工作,你可以像推送第一个分支那样推送它。

git push origin serverfix

​ 这里有些工作被简化了。 Git 自动将 serverfix 分支名字展开为 refs/heads/serverfix:refs/heads/serverfix 你也可以运行 git push origin serverfix:serverfix。它会做同样的事 相当于它说, 推送本地的 serverfix 分支,将其作为远程仓库的 serverfix 分支。

git push origin serverfix:awesomebranch 如果并不想让远程仓库上的分支叫做 serverfix ,可以运行 以上命令 将本地的 serverfix 分支推送到远程仓库上 的 awesomebranch 分支 。 git fetch origin

​ 下一次其他协作者从服务器上抓取数据时,他们会在本地生成一个远程 跟 踪 分支 origin/serverfix ,指向服务器的 serverfix 分支的引用 。 要特别注意的一点是当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本(拷贝)。 换一句话说,这种情况下,不会有一个新的serverfix分支只有一个不可以修改origin/ serverfix指针 。

git merge origin/serverfix ( 其他协作者)

​ 可以运行 git merge origin/serverfix 将这些工作合并到当前所在的分支。 如果想要在自己的 serverfix 分支上工作,可以将其建立在远程跟踪分支之上:

git checkout b serverfix origin/serverfix (其他协作者) 跟踪分支

​ 从一个远程跟踪分支( origin/master) 检出一个本地分支会自动创建一个叫做 “ 跟踪分支 ”(有时候也叫做 “上游分支 ”: master )。只有主分支 并且 克隆时才会自动建跟踪分支。跟踪分支是与远程分支有直接关系的本地分支。 如果在一个跟踪分支上输入 git pull。Git 能自动地识别去哪个服务器上抓取、合并到哪个分支 。

删除远程分支 git push origin --delete serverfix //删除远程分支 git remote prune origin --dry --run //列出仍在远程跟踪但是远程已被删除的无用分支 git remote prune origin // 清除上面命令列出来的远程跟踪 「拉取操作」

​ 如果你想要参与某个项目,但是并没有推送权限,这时可以对这个项目进行“派生”( Fork )。 派 生的意思是指, GitHub 将在你的空间中创建一个完全属于你的项目副本,且你对其具有推送权限。通过这种方式,项目的管理者不再需要忙着把用户添加到贡献者列表并给予他们推送权限。 人们可以派生这个项目,将修改推送到派生出的项目副本中,并通过创建合并请求( Pull Request )来让他们的改动进入源版本库。

派生(Fork)基本流程: 1. 从 master 分支中创建一个新分支 (自己 fork 的项目) 2. 提交一些修改来改进项目 (自己 fork 的项目) 3. 将这个分支推送到 GitHub 上 (自己 fork 的项目) 4. 创建一个合并请求 5. 讨 论,根据实际情况继续修改 6. 项目的拥有者合并或关闭你的合并请求 派生注意点:

​ 每次在发起新的Pull Request 时 要去拉取最新的源仓库的代码而不是自己 fork 的那个仓库。

git remote add Feature 注7:可以使用git mergetool来使用外部merge工具(可以在c:/users//.gitconfig文件配置beyond compare作为默认的mergetool)来处理冲突。 修改完当前文件后,可再次调用git mergetool来处理下一个冲突,直至全部处理完毕,然后使用git add该文件,最后继续执行git merge/rebase --continue来完成合并的提交工作 git merge/rebase --abort // 撤销当前merge或rebase操作 git merge/rebase --skip // 强制使用Feature分支的内容 git merge/rebase --continue // 手动处理完冲突后使用git add该文件,最后继续执行git merge/rebase --continue来完成合并的提交工作 git merge origin/master // fetch完之后,可以将远程分支cache master分支merge合并到当前分支上 git rebase origin/master // fetch完之后,可以将远程分支cache master分支rebase合并到当前分支上 git rebase --onto master 76cada~ // 将当前分支从[76cada, HEAD]区间段的提交ebase合并到master上 git cherry-pick 9a341e // 将9a341e提交合入当前分支。若不冲突,则直接使用9a341e的提交信息进行commit,否则要先进行冲突处理,然后继续执行git cherry-pick --continue来完成合并的提交工作 git cherry-pick 371c2…971209 // 将(371c2, 971209]提交合入当前分支(每个提交都会在当前分支上创建一个commit) git cherry-pick 371c2~…971209 // 将 [371c2, 971209] 提交合入当前分支(每个提交都会在当前分支上创建一个commit) git cherry-pick -n 9a341e d2f99e // 将9a341e和d2f99e提交合入当前分支(不提交),后续需要手动commit git cherry-pick --abort // 撤销当前cherry-pick操作 git cherry-pick --quit // 清理当前操作状态,不撤销修改强制退出cherry-pick操作过程 git cherry-pick --continue // 手动处理完冲突后,最后继续执行git cherry-pick --continue来完成合并的提交工作 查看远程版本库 git remote -v // 显示远程仓库的URL 注:由于git是分布式的,所有远程仓库可能有很多个 origin https://github.com/kekec/Test.git (fetch) origin https://github.com/kekec/Test.git (push) git remote-ls // 查看远程仓库URL和分支信息 From https://github.com/kekec/Test.git fae0fc82d711425daa897a63137d7e1af09512ba HEAD fae0fc82d711425daa897a63137d7e1af09512ba refs/heads/master git remote // 查看远程仓库名称 一般为origin git remote rename origin test // 将远程仓库名称从origin修改为test git remote show origin // 显示远程仓库的信息 * remote origin Fetch URL: https://github.com/kekec/Test.git Push URL: https://github.com/kekec/Test.git HEAD branch: master Remote branches: master tracked v3.1 tracked Local branch configured for 'git pull': master merges with remote master Local refs configured for 'git push': master pushes to master (fast-forwardable) v3.1 pushes to v3.1 (up to date) git remote rm origin // 删除.git/config文件中添加remote origin相关的信息 git remote add origin https://github.com/kekec/Test.git // 在.git/config文件中添加remote origin指向的远程仓库URL(若已存在,则命令执行失败) git remote set-url origin https://github.com/kekec/Test.git // 修改.git/config文件中添加remote origin指向的远程仓库URL git remote prune origin // 对于远程仓库不存在的分支,清除对应的远程分支cache 远程操作 git clone https://github.com/kekec/Test.git // 将https://github.com/kekec/Test.git上的当前分支克隆到本地(会创建一个名为Test目录,远程仓库名称使用默认名origin) git clone https://username:[email protected]/kekec/Test.git // 使用账号为username密码为password将https://github.com/kekec/Test.git上的当前分支克隆到本地(会创建一个名为Test目录,远程仓库名称使用默认名origin) git clone https://github.com/kekec/Test.git MyProject // 将https://github.com/kekec/Test.git上的当前分支克隆到本地(会创建一个名为MyProject目录,远程仓库名称使用默认名origin) git clone -b v1.0 https://github.com/kekec/Test.git // 将https://github.com/kekec/Test.git上的v1.0分支克隆到本地(会创建一个名为Test目录,远程仓库名称使用默认名origin) git clone -b v1.0 https://github.com/kekec/Test.git d:\MyGame // 将https://github.com/kekec/Test.git上的v1.0分支克隆到d:\MyGame目录(会在d:\MyGame中创建一个名为Test目录,远程仓库名称使用默认名origin) git clone -o TestPrj https://github.com/kekec/Test.git // 将https://github.com/kekec/Test.git上的当前分支克隆到本地(会创建一个名为Test目录,并将远程仓库名称设置为TestPrj) git fetch origin master // 从远程仓库拉取master分支状态的变化信息(工作区文件不会更新) git fetch // 从远程仓库拉取所有分支和tag状态的变化信息(工作区文件不会更新) git fetch -p // 从远程仓库拉取所有分支和tag状态的变化信息,并清除已被删除的远程分支和tag在本地的缓存(工作区文件不会更新) git fetch origin --tags // 从远程仓库拉取所有tag到本地(工作区文件不会更新) git pull : git pull origin master // 先执行fetch,然后将远程origin/master分支merge合并到当前分支(最后会更新origin/master, origin/HEAD指针到最新提交) git pull https://github.com/kekec/Test.git master // 先执行fetch,将远程origin/master分支merge合并到当前分支(最后不会更新origin/master, origin/HEAD指针到最新提交) git pull origin v1.0:master // 先执行fetch,然后将远程origin/v1.0分支merge合并到本地master分支 git pull origin // 先执行fetch,然后将对应的远程分支merge合并到当前分支(当前分支需要预存远程分支的追踪关系) git pull // 先执行fetch,然后将对应的远程分支merge合并到当前分支(当前分支需要预存远程分支的追踪关系,而且当前分支只有一个远程仓库) git pull -p // 先执行fetch,然后将对应的远程分支merge合并到当前分支,并清除已被删除的远程分支和tag在本地的缓存 git pull -r origin master // 先执行fetch,然后将远程origin/master分支rebase合并到master分支 git push : git push -u origin master // 将本地仓库的修改push到origin所指向的远程仓库URL的master分支上,并在.git/config文件中记录当前分支与远程分支master的对应关系 git push origin // 将当前分支更新推送给对应的远端分支 git push // 将当前分支更新推送给对应的远端分支(当前分支只有一个远程仓库,可以省略仓库名origin) git push origin -f // 使用当前分支更新强行覆盖对应的远端分支(合入远端分支有冲突时,也使用当前分支更新) git push origin v1.0 // 将本地分支v1.0更新推送给对应的远端分支remotes/origin/v1.0 git push --set-upstream origin v1.0 // 将本地分支v1.0更新推送给对应的远端分支remotes/origin/v1.0,并将建立与远程分支origin/v1.0的追踪关系 git push origin --all // 将本地所有分支更新推送给各自对应的远端分支 git push origin tag1.0 // 将本地标签tag1.0更新到远端标签tag1.0 git push origin --tags // 将本地所有标签更新到对应的远端标签 git push origin :v1.0 // 删除远端分支v1.0 git push origin :refs/tags/tag1.0 // 删除远程标签tag1.0 git push origin -d v1.0 // 删除远端分支v1.0 功能同上 储藏区 git stash // 将工作区中所有文件的修改备份压栈到储藏区,然后丢弃工作区与暂存区的所有文件的修改 git stash pop // 使用储藏区的栈顶处备份(stash@{0})来恢复当前分支的工作区,并将栈顶备份移除 git stash apply stash@{1} // 使用储藏区的栈顶下面一个备份(stash@{1})来恢复当前分支的工作区,但不移除储藏区中任何备份 git stash list // 查看储藏区栈列表 git stash show -p stash@{0} // 查看储藏区的栈顶处备份中各个文件的内容 git stash drop // 直接移除储藏区的栈顶处备份(不用于恢复当前分支的工作区) git stash clear // 清除储藏区栈列表 工作区 git clean -nd // 探测工作区中有哪些未追踪状态的文件和目录 git clean -fd // 删除工作区中未追踪状态的文件和目录 暂存区 git ls-files // 查询暂存区中的文件列表(递归子目录) git ls-files -s // 查看暂存区中所有文件的blob数据块信息 git ls-files -s -- README.md // 查看暂存区中的README.md文件的blob数据块信息 其他命令 git fsck --full // 列出所有未引用的blob、tree、commit对象 git archive --format zip --output d:/file.zip master // 将当前master分支所有文件使用zip压缩方式打包到d:/file.zip Git瘦身 git count-objects -v // 查看git对象的统计信息 find .git/objects -type f -print0 | xargs -0 du -hk | sort -nr | head -5 // 查找git库中最大的5个文件(du -hk中的k代表单位为KB) find .git/objects -type f -size +1M -print0 | xargs -0 du -hm | sort -nr | head -5 // 查找git库中size超过1M的最大的5个文件(du -hm中的k代表单位为MB) git verify-pack -v .git/objects/pack/pack-b340eea7566df839294b71ec91a327ca2ece0b94.idx | sort -k 3 -nr | head -5 // 对压缩存储的git库查找最大的5个文件 git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch FramePro.cpp' --prune-empty --tag-name-filter cat -- --all // 从git库的历史记录中彻底清理FramePro.cpp git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin // 清理所有废弃的ref引用 git gc --prune=now // ①将所有的对象压缩存储到pack二进制文件中,以节省空间和提高效率 ②移除与任何提交都不相关的陈旧对象 git reflog expire --expire=now --all // 清除所有操作记录日志 除了使用git原生命令外,可以使用专门的工具BFG(java实现)来对Git库瘦身 经典GItflow

img

(1) master分支存储了正式发布的历史(master分支上的所有提交都会分配一个版本号) (2) develop分支作为功能的集成分支 (3) 每个新功能位于一个自己的Feature分支,该分支使用develop分支作为父分支。当新功能完成时,合并回develop分支。新功能提交应该从不直接与master分支交互 (4) 一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从develop分支上fork一个release分支。 新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上。 这个分支只应该做Bug修复、文档生成和其它面向发布任务。 对外发布的工作完成后,发布分支会合并到master分支并分配一个版本号打好Tag。另外,这些从新建发布分支以来的做的修改要合并回develop分支。 (5) hotfix分支用于生成快速给产品发布版本(production releases)打补丁,修复完成,修改应该马上合并回master分支(打好Tag)和develop分支(当前的发布分支)。

git ls-files -s – README.md // 查看暂存区中的README.md文件的blob数据块信息

### 其他命令

git fsck --full // 列出所有未引用的blob、tree、commit对象

git archive --format zip --output d:/file.zip master // 将当前master分支所有文件使用zip压缩方式打包到d:/file.zip

### Git瘦身

git count-objects -v // 查看git对象的统计信息

find .git/objects -type f -print0 | xargs -0 du -hk | sort -nr | head -5 // 查找git库中最大的5个文件(du -hk中的k代表单位为KB)

find .git/objects -type f -size +1M -print0 | xargs -0 du -hm | sort -nr | head -5 // 查找git库中size超过1M的最大的5个文件(du -hm中的k代表单位为MB)

git verify-pack -v .git/objects/pack/pack-b340eea7566df839294b71ec91a327ca2ece0b94.idx | sort -k 3 -nr | head -5 // 对压缩存储的git库查找最大的5个文件

git filter-branch --force --index-filter ‘git rm --cached --ignore-unmatch FramePro.cpp’ --prune-empty --tag-name-filter cat – --all // 从git库的历史记录中彻底清理FramePro.cpp

git for-each-ref --format=‘delete %(refname)’ refs/original | git update-ref --stdin // 清理所有废弃的ref引用

git gc --prune=now // ①将所有的对象压缩存储到pack二进制文件中,以节省空间和提高效率 ②移除与任何提交都不相关的陈旧对象

git reflog expire --expire=now --all // 清除所有操作记录日志

除了使用git原生命令外,可以使用专门的工具BFG(java实现)来对Git库瘦身

### 经典GItflow [外链图片转存中...(img-d3yWshWh-1625702843730)]

(1) master分支存储了正式发布的历史(master分支上的所有提交都会分配一个版本号)

(2) develop分支作为功能的集成分支

(3) 每个新功能位于一个自己的Feature分支,该分支使用develop分支作为父分支。当新功能完成时,合并回develop分支。新功能提交应该从不直接与master分支交互

(4) 一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从develop分支上fork一个release分支。 新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上。 这个分支只应该做Bug修复、文档生成和其它面向发布任务。 对外发布的工作完成后,发布分支会合并到master分支并分配一个版本号打好Tag。另外,这些从新建发布分支以来的做的修改要合并回develop分支。

(5) hotfix分支用于生成快速给产品发布版本(production releases)打补丁,修复完成,修改应该马上合并回master分支(打好Tag)和develop分支(当前的发布分支)。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3